using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

namespace Departure
{
    public partial class ctrlCountdown : UserControl
    {

        public delegate void CountdownFinishedEventHandler();
        public event CountdownFinishedEventHandler OnCountdownFinished;


        TimeSpan countDown;
        DateTime alarmDate;
        string alarmText = string.Empty;
        string trainText = string.Empty;
        string laterText = string.Empty;
        bool running = false;
        SkinSettings skinSettings;

        bool vga = false;

        // Background drawing
        Bitmap backBufferBitmap;
        Graphics backBuffer;

        public ctrlCountdown()
        {
            InitializeComponent();

            CreateBackBuffer();

            tmrCountdown.Enabled = true;
        }

        public void Start(DateTime alarmTime, string train, string later)
        {
            this.alarmDate = alarmTime;
            this.trainText = train;
            this.laterText = later;

            running = true;
        }

        public void Stop()
        {
            running = false;
        }

        public void StartTimer()
        {
            tmrCountdown.Enabled = true;
        }

        public void StopTimer()
        {
            tmrCountdown.Enabled = false;
        }

        public bool isRunning
        {
            get
            {
                return running;
            }
        }

        public SkinSettings SkinSettings
        {
            get
            {
                return skinSettings;
            }
            set
            {
                skinSettings = value;
                Invalidate();
            }
        }

        public bool VGA
        {
            get { return this.vga; }
            set { this.vga = value; }
        }

        public static Font AppropriateFont(Graphics g, float minFontSize, float maxFontSize, Size layoutSize, string s, Font f, out SizeF extent)
        {
            if (maxFontSize == minFontSize)
                f = new Font(f.Name, minFontSize, f.Style);

            extent = g.MeasureString(s, f);

            if (maxFontSize <= minFontSize)
                return f;

            float hRatio = layoutSize.Height / extent.Height;
            float wRatio = layoutSize.Width / extent.Width;
            float ratio = (hRatio < wRatio) ? hRatio : wRatio;

            float newSize = f.Size * ratio;

            if (newSize < minFontSize)
                newSize = minFontSize;
            else if (newSize > maxFontSize)
                newSize = maxFontSize;

            f = new Font(f.Name, newSize, f.Style);
            extent = g.MeasureString(s, f);

            return f;
        }
        
        private void tmrCountdown_Tick(object sender, EventArgs e)
        {
            try
            {
                if (running)
                {
                    countDown = alarmDate - DateTime.Now;
                    alarmText = countDown.Hours.ToString("00") + ":" + countDown.Minutes.ToString("00") + ":" + countDown.Seconds.ToString("00");

                    if (countDown.TotalSeconds < 1)
                    {
                        tmrCountdown.Enabled = false;
                        alarmText = "00:00:00";

                        if (OnCountdownFinished != null)
                            OnCountdownFinished();
                    }
                }
                else
                {
                    alarmText = "Stopped";
                }

                Invalidate();

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// Paints the background of the control.
        /// </summary>
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            // Do nothing
        }

        /// <summary>
        /// Paints the control.
        /// </summary>
        protected override void OnPaint(PaintEventArgs e)
        {
            if (backBuffer != null)
            {
                SizeF size;

                if (vga)
                {
                    backBuffer.DrawImage(skinSettings.BackGround, this.Bounds, e.ClipRectangle, GraphicsUnit.Pixel);
                    //backBuffer.Clear(Color.Green);

                    if (running)
                    {
                        using (Font f2 = AppropriateFont(backBuffer, 5, 200, new Size(this.Bounds.Width, 32), trainText, this.Font, out size))
                        {
                            backBuffer.DrawString(trainText, f2, new SolidBrush(skinSettings.FontColor), (this.Bounds.Width - size.Width) / 2, (32 - size.Height) / 2);
                        }
                    }

                    string currentText = DateTime.Now.ToString();

                    using (Font f2 = AppropriateFont(backBuffer, 5, 200, new Size(this.Bounds.Width, 32), currentText, this.Font, out size))
                    {
                        backBuffer.DrawString(currentText, f2, new SolidBrush(skinSettings.FontColor), (this.Bounds.Width - size.Width) / 2, ((32 - size.Height) / 2) + 32);
                    }

                    using (Font f2 = AppropriateFont(backBuffer, 5, 200, new Size(this.Size.Width, this.Bounds.Height - 96), alarmText, this.Font, out size))
                    {
                        if (laterText == "")
                            backBuffer.DrawString(alarmText, f2, new SolidBrush(skinSettings.FontColor), (this.Bounds.Width - size.Width) / 2, (this.Bounds.Height - size.Height) / 2);
                        else
                            backBuffer.DrawString(alarmText, f2, new SolidBrush(skinSettings.LaterColor), (this.Bounds.Width - size.Width) / 2, (this.Bounds.Height - size.Height) / 2);
                    }

                    using (Font f2 = AppropriateFont(backBuffer, 5, 200, new Size(this.Bounds.Width, 32), laterText, this.Font, out size))
                    {
                        backBuffer.DrawString(laterText, f2, new SolidBrush(skinSettings.LaterColor), (this.Bounds.Width - size.Width) / 2, this.Bounds.Height - size.Height);
                    }

                    e.Graphics.DrawImage(backBufferBitmap, 0, 0);
                }
                else
                {

                    backBuffer.DrawImage(skinSettings.BackGround, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);

                    if (running)
                    {
                        using (Font f2 = AppropriateFont(backBuffer, 5, 200, new Size(this.Bounds.Width, 16), trainText, this.Font, out size))
                        {
                            backBuffer.DrawString(trainText, f2, new SolidBrush(skinSettings.FontColor), (this.Bounds.Width - size.Width) / 2, (16 - size.Height) / 2);
                        }
                    }

                    string currentText = DateTime.Now.ToString();

                    using (Font f2 = AppropriateFont(backBuffer, 5, 200, new Size(this.Bounds.Width, 16), currentText, this.Font, out size))
                    {
                        backBuffer.DrawString(currentText, f2, new SolidBrush(skinSettings.FontColor), (this.Bounds.Width - size.Width) / 2, ((16 - size.Height) / 2) + 16);
                    }

                    using (Font f2 = AppropriateFont(backBuffer, 5, 200, new Size(this.Size.Width, this.Bounds.Height - 48), alarmText, this.Font, out size))
                    {
                        if (laterText == "")
                            backBuffer.DrawString(alarmText, f2, new SolidBrush(skinSettings.FontColor), (this.Bounds.Width - size.Width) / 2, (this.Bounds.Height - size.Height) / 2);
                        else
                            backBuffer.DrawString(alarmText, f2, new SolidBrush(skinSettings.LaterColor), (this.Bounds.Width - size.Width) / 2, (this.Bounds.Height - size.Height) / 2);
                    }

                    using (Font f2 = AppropriateFont(backBuffer, 5, 200, new Size(this.Bounds.Width, 16), laterText, this.Font, out size))
                    {
                        backBuffer.DrawString(laterText, f2, new SolidBrush(skinSettings.LaterColor), (this.Bounds.Width - size.Width) / 2, this.Bounds.Height - size.Height);
                    }

                    e.Graphics.DrawImage(backBufferBitmap, 0, 0);
                }
            }
            else
            {
                base.OnPaint(e);
            }
        }

        /// <summary>
        /// Called when the control is resized.
        /// </summary>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            CreateBackBuffer();
            Invalidate();
        }

        /// <summary>
        /// Cleans up the background paint buffer.
        /// </summary>
        private void CleanupBackBuffer()
        {
            if (backBufferBitmap != null)
            {
                backBufferBitmap.Dispose();
                backBufferBitmap = null;
                backBuffer.Dispose();
                backBuffer = null;
            }
        }

        /// <summary>
        /// Creates the background paint buffer.
        /// </summary>
        private void CreateBackBuffer()
        {
            CleanupBackBuffer();

            backBufferBitmap = new Bitmap(Bounds.Width, Bounds.Height);
            backBuffer = Graphics.FromImage(backBufferBitmap);
        }
    }
}
